package com.excel.poi.ali;

import com.excel.entity.ExcelTable;
import com.excel.poi.ali.inter.AnalysisContextImpl;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zw
 * @Description xlsx解析
 * @create /2022/3/24
 */
public class XlsxSaxAnalyser extends BaseSaxAnalyser {
    private XSSFReader xssfReader;
  // 从 XML 文件中读取此共享字符串表。
    private SharedStringsTable sharedStringsTable;
   //存储 每个sheet名字和每个sheet流
    private List<SheetSource> sheetSourceList = new ArrayList<SheetSource>();

    private boolean use1904WindowDate = false;

    public XlsxSaxAnalyser(AnalysisContextImpl analysisContext) throws IOException, OpenXML4JException, XmlException {
        this.analysisContext = analysisContext;

        analysisContext.setCurrentRowNum(0);
        this.xssfReader = new XSSFReader(OPCPackage.open(analysisContext.getInputStream()));
        this.sharedStringsTable = this.xssfReader.getSharedStringsTable();

        InputStream workbookXml = xssfReader.getWorkbookData();
        WorkbookDocument ctWorkbook = WorkbookDocument.Factory.parse(workbookXml);
        CTWorkbook wb = ctWorkbook.getWorkbook();
        CTWorkbookPr prefix = wb.getWorkbookPr();
        if (prefix != null) {
            this.use1904WindowDate = prefix.getDate1904();
        }
        this.analysisContext.setUse1904WindowDate(use1904WindowDate);


        XSSFReader.SheetIterator ite;
        sheetSourceList = new ArrayList<SheetSource>();
        ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
        while (ite.hasNext()) {
            InputStream inputStream = ite.next();
            String sheetName = ite.getSheetName();
            SheetSource sheetSource = new SheetSource(sheetName, inputStream);
            sheetSourceList.add(sheetSource);
        }

    }

    public void execute() throws Exception {
        SheetParam sheetParam = analysisContext.getCurrentSheet();
        if (sheetParam != null && sheetParam.getSheetNo() > 0 && sheetSourceList.size() >= sheetParam.getSheetNo()) {
            InputStream sheetInputStream = sheetSourceList.get(sheetParam.getSheetNo() - 1).getInputStream();
            parseXmlSource(sheetInputStream);

        } else {
            int i = 0;
            for (SheetSource sheetSource : sheetSourceList) {
                i++;
                //构建解析前准备 反射出类的名称，头占行等属性
                analysisContext.setCurrentSheet(new SheetParam(i,1, analysisContext.getC1()));
                parseXmlSource(sheetSource.getInputStream());
            }
        }
    }

    /**
     * 解析xml资源
     * @param inputStream
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    private void parseXmlSource(InputStream inputStream)
        throws IOException, SAXException, ParserConfigurationException {
        InputSource sheetSource = new InputSource(inputStream);
        try {
            SAXParserFactory saxFactory = SAXParserFactory.newInstance();
            saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
            saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            SAXParser saxParser = saxFactory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            ContentHandler handler = new XlsxRowHandler(this, sharedStringsTable, analysisContext);
            xmlReader.setContentHandler(handler);
            xmlReader.parse(sheetSource);
            inputStream.close();
        } catch (Exception e) {
            throw e;
        }
    }

    public List<SheetParam> getSheets() {
        List<SheetParam> sheets = new ArrayList<SheetParam>();
        int i = 1;
        for (SheetSource sheetSource : sheetSourceList) {
            SheetParam sheet = new SheetParam(i, 0);
            sheet.setSheetName(sheetSource.getSheetName());
            i++;
            sheets.add(sheet);
        }

        return sheets;
    }
  @Data
  @AllArgsConstructor
    class SheetSource {
        // 当前sheet名
        private String sheetName;
        //当前sheet的流
        private InputStream inputStream;
    }
}
